package salesalert

import com.the6hours.grails.springsecurity.facebook.FacebookAuthDao
import com.the6hours.grails.springsecurity.facebook.FacebookAuthToken
import org.springframework.security.core.GrantedAuthority
import org.apache.log4j.Logger
import org.springframework.security.core.authority.GrantedAuthorityImpl
import org.springframework.social.facebook.api.Facebook
import org.springframework.social.facebook.api.FacebookProfile
import org.springframework.social.facebook.api.impl.FacebookTemplate

/**
 * Autogenerated implementation of FacebookAuthDao
 *
 */
class FacebookAuthDaoImpl implements FacebookAuthDao<User>  {

	private static def log = Logger.getLogger(this)

	/**
	 * Tries to load app user for Facebook user
	 *
	 * @param uid UID of Facebook user
	 * @return existing user, or null if there is no user for specified uid
	 */
	User findUser(long uid) {
		User user = User.findByUid(uid)
		if (user) {
			return user
		}
		return null
	}

	/**
	 * Called when logged in facebook user doesn't exists in current database
	 *
	 * @param token information about current authnetication
	 * @return just created user
	 */
	User create(FacebookAuthToken token) {
		User user = null
		try {
			user = createFacebookCredential(token)
		} catch (Exception e) {
			e.printStackTrace()
		}
		return user
	}
	
	User createFacebookCredential(FacebookAuthToken token) {
		Facebook facebook = new FacebookTemplate(token.accessToken)
		FacebookProfile fbProfile = facebook.userOperations().userProfile
		String email = fbProfile.getEmail()

		User user = FacebookCredential.findByUid(token.uid)
		if (user && user.active) {
			return user
		}

			if (user == null) {
				user = new User(uid: token.uid)
			}

			user.accessToken = token.accessToken

			user = user.merge()
			user.save()

			if(user.hasErrors()) {
				user.errors.allErrors.each { println it }
			}

		return user
	}

	/**
	 * Called when facebook auth token has been changed
	 *
	 * @param user updates used details
	 */
	void update(User user) {
		//TODO change regarding your domains structure
		User.withTransaction { user.save() }
	}

	/**
	 * Returns `principal` that will be stored into Security Context. It's good if it
	 * implements {@link org.springframework.security.core.userdetails.UserDetails UserDetails} or
	 * {@link java.security.Principal Principal}.
	 *
	 * At most cases it's just current user, passed as parameter
	 *
	 * @param user current user
	 * @return user to put into Security Context
	 */
	Object getPrincipal(User user) {
		//TODO change regarding your domains structure
		return user;
	}

	/**
	 * Roles for current user
	 *
	 * @param user current user
	 * @return roles for user
	 */
	Collection<GrantedAuthority> getRoles(User user) {
		//TODO change regarding your domains structure
		Collection<GrantedAuthority> roles = [
			new GrantedAuthorityImpl('ROLE_USER'),
			new GrantedAuthorityImpl('ROLE_FACEBOOK')
		]
		return roles
	}

}
